#!/usr/bin/python

#    This file is part of meterserv - a simple utility to log and display
#    readings from utility meters (see http://meterserv.webhop.net)
#
#    Meterserv is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Townguide is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with townguide.  If not, see <http://www.gnu.org/licenses/>.
#
#    Copyright Graham Jones 2011
#
# Based on the excellent webpy tutorial at 
# http://kooneiform.wordpress.com/2010/02/28/python-and-ajax-for-beginners-with-webpy-and-jquery/


import web
import model

def make_text(string):
    return string

urls = ('/', 'meterserv_home',
        '/admin', 'admin',
        '/admin/editmeter/(.*)','edit_meter',
        '/readings', 'selreadings',
        '/getdates','getdates',
        '/readings/(.*)', 'readings',
        '/getdata','getdata',
)
render = web.template.render('templates/',base='base')
app = web.application(urls, globals())


class meterserv_home:
    def GET(self):
        web.debug("meterserv_home.GET()")
        return render.meterserv_home()
        
    def POST(self):
        return "meterserv_home.POST()"


class admin:
    def GET(self):
        web.debug("admin.GET()")
        meterlist = model.get_meters()
        web.debug(meterlist)
        return render.meterserv_admin(meterlist)
        
    def POST(self):
        return "meterserv_admin.POST()"

class edit_meter:
    meter_form = web.form.Form(
        web.form.Textbox('description', web.form.notnull, 
            size=15,
            description="description:"),
        web.form.Textbox('unit', web.form.notnull, 
            size=6,
            description="unit:"),
        web.form.Textbox('reading', 
            web.form.regexp('[-+]?[0-9]*\.?[0-9]+', 'Must be a number'), 
            size=6,
            description="reading:"),
        web.form.Textbox('output_period', 
            web.form.regexp('^-?\d+$', 'Must be an integer'), 
            size=6,
            description="Output Period (sec):"),
        web.form.Textbox('iocard', 
            web.form.regexp('^-?\d+$', 'Must be an integer'), 
            size=3,
            description="I/O Card Number:"),
        web.form.Textbox('input',  
            web.form.regexp('^-?\d+$', 'Must be an integer'), 
            size=3,
            description="input number:"),
        web.form.Textbox('cfac',  
            web.form.regexp('[-+]?[0-9]*\.?[0-9]+', 'Must be a number'), 
            size=6,
            description="Conversin Factor (from pulses to units):"),
        web.form.Button('Submit Changes'),
    )
    def GET(self,meterid):
        web.debug("edit_meter.GET() - meterid=%d" % (int(meterid)))
        meterdata = model.get_meter(meterid)
        web.debug(meterdata)
        form = self.meter_form()
        form.fill(meterdata)
        return render.meterserv_edit_meter(meterdata,form)
        
    def POST(self,meterid):
        mform = self.meter_form()
        
        if mform.validates():
            validStr = "Form Data OK"
            model.update_meter(meterid,
                               mform.d.description,
                               mform.d.unit,
                               mform.d.cfac,
                               mform.d.output_period,
                               mform.d.iocard,
                               mform.d.input,
                               mform.d.reading)
            meterdata = model.get_meter(meterid)
            web.debug(meterdata)
            form = self.meter_form()
            form.fill(meterdata)
            return render.meterserv_edit_meter(meterdata,form)
        else:
            validStr = "Form Contains Errors - Please Correct!\n"
            for k in mform.inputs: 
                if k.note != None:
                    validStr += \
                        "id = %s: Value=%s: Error=%s\n" % \
                        (k.id,k.value,k.note)
        return validStr

class selreadings:
    def GET(self):
        web.debug("selreadings.GET()")
        meterlist = model.get_meters()
        web.debug(meterlist)
        return render.meterserv_selReadings(meterlist)

    def POST(self):
        return "calling readings with post....does nothing"

class getdates:
    def GET(self):
        web.debug("getdates.GET()")
        meterID = int(web.input()['meter'])
        dates = model.get_dates(meterID)
        web.debug(dates)
        return dates



class readings:
    def GET(self,meterid):
        web.debug("readings.GET() - meterid=%d" % (int(meterid)))
        readings = model.get_readings(meterid)
        web.debug(readings)
        return render.list_readings(readings)        
        
    def POST(self):
        return "calling readings with post....does nothing"

class getdata:
    def GET(self):
        web.debug("getdata.GET()")
        web.debug(web.input())
        outputPeriod = web.input()['outputPeriod']
        endDate = web.input()['endDate']
        summaryType = web.input()['summaryType']
        meterID = int(web.input()['meter'])

        web.debug("meterID=%d" % meterID)
        web.debug("outputPeriod=%s" % outputPeriod)

        dateFormatStr = "%Y-%m-%d %H:%M"

        if summaryType=='rawData':
            web.debug("rawData")
            dateSelStr = 'time'
            groupByClause = ''
            readingSelClause = "reading"
        elif summaryType == 'dailyAverage':
            web.debug("dailyAverage")
            dateSelStr = "time,'start of day'"
            readingSelClause = "min(reading)"
            groupByClause = ' group by seltime'
        elif summaryType == 'weeklyAverage':
            web.debug("weeklyAverage")
            dateSelStr = "time,'start of day','weekday 1'"
            readingSelClause = "min(reading)"
            groupByClause = ' group by seltime'
        elif summaryType == 'monthlyAverage':
            web.debug("monthlyAverage")
            dateSelStr = "time,'start of month'"
            readingSelClause = "min(reading)"
            groupByClause = ' group by seltime'
        else:
            web.debug("***ERROR - Unrecognised summaryType '%s'" % summaryType)
            dateSelStr=''
            readingSelClause = "reading"
            groupByClause = ''

        endPeriodWhereClause = \
            " and time <= date('%s','start of day','+1 day') " \
            % endDate
        if outputPeriod=="Day":
            startPeriodWhereClause = \
                " and time >= date('%s','start of day')" % endDate
        elif outputPeriod=="Month":
            startPeriodWhereClause = \
                " and time >= date('%s','start of day','-1 month')" % endDate
        elif outputPeriod=="Year":
            startPeriodWhereClause = \
                " and time >= date('%s','start of day','-1 year')" % endDate
        else:
            web.debug("***ERROR - Unrecognised outputPeriod '%s'" 
                      % outputPeriod)

        web.debug("startPeriodWhereClause = %s" % startPeriodWhereClause)
        web.debug("endPeriodWhereClause = %s" % endPeriodWhereClause)


        sqlStr = "select strftime('%s',%s) as seltime, "\
                  "%s as min_reading, "\
                  "julianday(%s) as jtime "\
                  "from readings  "\
                  "     where meter=%d "\
                  "           %s  "\
                  "           %s  "\
                  "     %s;" \
            % (dateFormatStr,dateSelStr,
               readingSelClause,
               dateSelStr,
               meterID,
               startPeriodWhereClause,
               endPeriodWhereClause,
               groupByClause)
        web.debug("sqlStr=%s" % sqlStr)

        results = model.query_db(sqlStr)
        outputStr = "<table border='1'>"
        outputStr+= "<tr><th>Date</th><th>Reading</th><th>Rate (/day)</th></tr>"
        first = True
        for rec in results:
            seltime = rec['seltime']
            minreading = rec['min_reading']
            jtime = rec['jtime']

            if first:
                rate = 0
                first = False
            else:
                rate = (minreading-lastminreading)/(jtime-lastjtime)

            web.debug("%s %+5.1f %+5.2f" % (seltime, minreading,rate))
            outputStr += "<tr><td>%s</td><td>%5.1f</td><td>%5.2f</td></tr>" %\
                (seltime, minreading,rate)

            lastseltime = seltime
            lastminreading = minreading
            lastjtime = jtime

        outputStr += "</table>"
        return outputStr

if __name__ == '__main__':
    app.run()

